home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / launchpadlib / launchpad.py < prev    next >
Text File  |  2009-07-13  |  11KB  |  263 lines

  1. # Copyright 2008-2009 Canonical Ltd.
  2.  
  3. # This file is part of launchpadlib.
  4. #
  5. # launchpadlib is free software: you can redistribute it and/or modify it
  6. # under the terms of the GNU Lesser General Public License as published by the
  7. # Free Software Foundation, version 3 of the License.
  8. #
  9. # launchpadlib is distributed in the hope that it will be useful, but WITHOUT
  10. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
  12. # for more details.
  13. #
  14. # You should have received a copy of the GNU Lesser General Public License
  15. # along with launchpadlib. If not, see <http://www.gnu.org/licenses/>.
  16.  
  17. """Root Launchpad API class."""
  18.  
  19. __metaclass__ = type
  20. __all__ = [
  21.     'Launchpad',
  22.     ]
  23.  
  24. import os
  25. import stat
  26. import sys
  27. import urlparse
  28. import webbrowser
  29.  
  30. from lazr.uri import URI
  31. from lazr.restfulclient._browser import RestfulHttp
  32. from lazr.restfulclient.resource import (
  33.     CollectionWithKeyBasedLookup, HostedFile, ServiceRoot)
  34. from launchpadlib.credentials import AccessToken, Credentials
  35. from oauth.oauth import OAuthRequest, OAuthSignatureMethod_PLAINTEXT
  36.  
  37. OAUTH_REALM = 'https://api.launchpad.net'
  38. STAGING_SERVICE_ROOT = 'https://api.staging.launchpad.net/beta/'
  39. EDGE_SERVICE_ROOT = 'https://api.edge.launchpad.net/beta/'
  40.  
  41.  
  42. class PersonSet(CollectionWithKeyBasedLookup):
  43.     """A custom subclass capable of person lookup by username."""
  44.  
  45.     def _get_url_from_id(self, key):
  46.         """Transform a username into the URL to a person resource."""
  47.         return str(self._root._root_uri.ensureSlash()) + '~' + str(key)
  48.  
  49.  
  50. class BugSet(CollectionWithKeyBasedLookup):
  51.     """A custom subclass capable of bug lookup by bug ID."""
  52.  
  53.     def _get_url_from_id(self, key):
  54.         """Transform a bug ID into the URL to a bug resource."""
  55.         return str(self._root._root_uri.ensureSlash()) + 'bugs/' + str(key)
  56.  
  57.  
  58. class PillarSet(CollectionWithKeyBasedLookup):
  59.     """A custom subclass capable of lookup by pillar name.
  60.  
  61.     Projects, project groups, and distributions are all pillars.
  62.     """
  63.  
  64.     def _get_url_from_id(self, key):
  65.         """Transform a project name into the URL to a project resource."""
  66.         return str(self._root._root_uri.ensureSlash()) + str(key)
  67.  
  68.  
  69. class Launchpad(ServiceRoot):
  70.     """Root Launchpad API class.
  71.  
  72.     :ivar credentials: The credentials instance used to access Launchpad.
  73.     :type credentials: `Credentials`
  74.     """
  75.  
  76.     RESOURCE_TYPE_CLASSES = {
  77.             'bugs': BugSet,
  78.             'distributions': PillarSet,
  79.             'HostedFile': HostedFile,
  80.             'people': PersonSet,
  81.             'project_groups': PillarSet,
  82.             'projects': PillarSet,
  83.             }
  84.  
  85.     def __init__(self, credentials, service_root=STAGING_SERVICE_ROOT,
  86.                  cache=None, timeout=None, proxy_info=None):
  87.         """Root access to the Launchpad API.
  88.  
  89.         :param credentials: The credentials used to access Launchpad.
  90.         :type credentials: `Credentials`
  91.         :param service_root: The URL to the root of the web service.
  92.         :type service_root: string
  93.         """
  94.         super(Launchpad, self).__init__(
  95.             credentials, service_root, cache, timeout, proxy_info)
  96.  
  97.     def httpFactory(self, credentials, cache, timeout, proxy_info):
  98.         return OAuthSigningHttp(credentials, cache, timeout, proxy_info)
  99.  
  100.     @classmethod
  101.     def login(cls, consumer_name, token_string, access_secret,
  102.               service_root=STAGING_SERVICE_ROOT,
  103.               cache=None, timeout=None, proxy_info=None):
  104.         """Convenience for setting up access credentials.
  105.  
  106.         When all three pieces of credential information (the consumer
  107.         name, the access token and the access secret) are available, this
  108.         method can be used to quickly log into the service root.
  109.  
  110.         :param consumer_name: the consumer name, as appropriate for the
  111.             `Consumer` constructor
  112.         :type consumer_name: string
  113.         :param token_string: the access token, as appropriate for the
  114.             `AccessToken` constructor
  115.         :type token_string: string
  116.         :param access_secret: the access token's secret, as appropriate for
  117.             the `AccessToken` constructor
  118.         :type access_secret: string
  119.         :param service_root: The URL to the root of the web service.
  120.         :type service_root: string
  121.         :return: The web service root
  122.         :rtype: `Launchpad`
  123.         """
  124.         access_token = AccessToken(token_string, access_secret)
  125.         credentials = Credentials(
  126.             consumer_name=consumer_name, access_token=access_token)
  127.         return cls(credentials, service_root, cache, timeout, proxy_info)
  128.  
  129.     @classmethod
  130.     def get_token_and_login(cls, consumer_name,
  131.                             service_root=STAGING_SERVICE_ROOT,
  132.                             cache=None, timeout=None, proxy_info=None):
  133.         """Get credentials from Launchpad and log into the service root.
  134.  
  135.         This is a convenience method which will open up the user's preferred
  136.         web browser and thus should not be used by most applications.
  137.         Applications should, instead, use Credentials.get_request_token() to
  138.         obtain the authorization URL and
  139.         Credentials.exchange_request_token_for_access_token() to obtain the
  140.         actual OAuth access token.
  141.  
  142.         This method will negotiate an OAuth access token with the service
  143.         provider, but to complete it we will need the user to log into
  144.         Launchpad and authorize us, so we'll open the authorization page in
  145.         a web browser and ask the user to come back here and tell us when they
  146.         finished the authorization process.
  147.  
  148.         :param consumer_name: The consumer name, as appropriate for the
  149.             `Consumer` constructor
  150.         :type consumer_name: string
  151.         :param service_root: The URL to the root of the web service.
  152.         :type service_root: string
  153.         :return: The web service root
  154.         :rtype: `Launchpad`
  155.         """
  156.         credentials = Credentials(consumer_name)
  157.         web_root_uri = URI(service_root)
  158.         web_root_uri.path = ""
  159.         web_root_uri.host = web_root_uri.host.replace("api.", "", 1)
  160.         web_root = str(web_root_uri.ensureSlash())
  161.         authorization_url = credentials.get_request_token(web_root=web_root)
  162.         webbrowser.open(authorization_url)
  163.         print "The authorization page:"
  164.         print "   (%s)" % authorization_url
  165.         print "should be opening in your browser. After you have authorized"
  166.         print "this program to access Launchpad on your behalf you should come"
  167.         print "back here and press <Enter> to finish the authentication process."
  168.         sys.stdin.readline()
  169.         credentials.exchange_request_token_for_access_token(web_root)
  170.         return cls(credentials, service_root, cache, timeout, proxy_info)
  171.  
  172.     @classmethod
  173.     def login_with(cls, consumer_name,
  174.                    service_root=STAGING_SERVICE_ROOT,
  175.                    launchpadlib_dir=None, timeout=None, proxy_info=None):
  176.         """Log in to Launchpad with possibly cached credentials.
  177.  
  178.         This is a convenience method for either setting up new login
  179.         credentials, or re-using existing ones. When a login token is
  180.         generated using this method, the resulting credentials will be
  181.         saved in the `launchpadlib_dir` directory. If the same
  182.         `launchpadlib_dir` is passed in a second time, the credentials
  183.         in `launchpadlib_dir` for the consumer will be used
  184.         automatically.
  185.  
  186.         Each consumer has their own credentials per service root in
  187.         `launchpadlib_dir`. `launchpadlib_dir` is also used for caching
  188.         fetched objects. The cache is per service root, and shared by
  189.         all consumers.
  190.  
  191.         See `Launchpad.get_token_and_login()` for more information about
  192.         how new tokens are generated.
  193.  
  194.         :param consumer_name: The consumer name, as appropriate for the
  195.             `Consumer` constructor
  196.         :type consumer_name: string
  197.         :param service_root: The URL to the root of the web service.
  198.         :type service_root: string
  199.         :param launchpadlib_dir: The directory where the cache and
  200.             credentials are stored.
  201.         :type launchpadlib_dir: string
  202.         :return: The web service root
  203.         :rtype: `Launchpad`
  204.  
  205.         """
  206.         if launchpadlib_dir is None:
  207.             home_dir = os.environ['HOME']
  208.             launchpadlib_dir = os.path.join(home_dir, '.launchpadlib')
  209.         launchpadlib_dir = os.path.expanduser(launchpadlib_dir)
  210.         # Each service root has its own cache and credential dirs.
  211.         scheme, host_name, path, query, fragment = urlparse.urlsplit(
  212.             service_root)
  213.         service_root_dir = os.path.join(launchpadlib_dir, host_name)
  214.         cache_path = os.path.join(service_root_dir, 'cache')
  215.         if not os.path.exists(cache_path):
  216.             os.makedirs(cache_path)
  217.         credentials_path = os.path.join(service_root_dir, 'credentials')
  218.         if not os.path.exists(credentials_path):
  219.             os.makedirs(credentials_path)
  220.         consumer_credentials_path = os.path.join(
  221.             credentials_path, consumer_name)
  222.         if os.path.exists(consumer_credentials_path):
  223.             credentials = Credentials.load_from_path(
  224.                 consumer_credentials_path)
  225.             launchpad = cls(
  226.                 credentials, service_root=service_root, cache=cache_path,
  227.                 timeout=timeout, proxy_info=proxy_info)
  228.         else:
  229.             launchpad = cls.get_token_and_login(
  230.                 consumer_name, service_root=service_root, cache=cache_path,
  231.                 timeout=timeout, proxy_info=proxy_info)
  232.             launchpad.credentials.save_to_path(
  233.                 os.path.join(credentials_path, consumer_name))
  234.             os.chmod(
  235.                 os.path.join(credentials_path, consumer_name),
  236.                 stat.S_IREAD | stat.S_IWRITE)
  237.         return launchpad
  238.  
  239.  
  240. class OAuthSigningHttp(RestfulHttp):
  241.     """A client that signs every outgoing request with OAuth credentials."""
  242.  
  243.     def _request(self, conn, host, absolute_uri, request_uri, method, body,
  244.                  headers, redirections, cachekey):
  245.         """Sign a request with OAuth credentials before sending it."""
  246.         oauth_request = OAuthRequest.from_consumer_and_token(
  247.             self.restful_credentials.consumer,
  248.             self.restful_credentials.access_token,
  249.             http_url=absolute_uri)
  250.         oauth_request.sign_request(
  251.             OAuthSignatureMethod_PLAINTEXT(),
  252.             self.restful_credentials.consumer,
  253.             self.restful_credentials.access_token)
  254.         if headers.has_key('authorization'):
  255.             # There's an authorization header left over from a
  256.             # previous request that resulted in a redirect. Remove it
  257.             # and start again.
  258.             del headers['authorization']
  259.         headers.update(oauth_request.to_header(OAUTH_REALM))
  260.         return super(OAuthSigningHttp, self)._request(
  261.             conn, host, absolute_uri, request_uri, method, body, headers,
  262.             redirections, cachekey)
  263.